﻿namespace MicroCloud.Utils
{
    /// <summary>
    /// 服务提供者接口辅助扩展方法类
    /// </summary>
    public static class ServiceProviderExtensions
    {
        #region ILoggerFactory
        /// <summary>
        /// 获取指定类型的日志对象
        /// </summary>
        /// <typeparam name="T">非静态强类型</typeparam>
        /// <returns>日志对象</returns>
        public static ILogger<T> GetLogger<T>(this IServiceProvider provider)
        {
            ILoggerFactory factory = provider.GetRequiredService<ILoggerFactory>();
            return factory.CreateLogger<T>();
        }

        /// <summary>
        /// 获取指定类型的日志对象
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="type">指定类型</param>
        /// <returns>日志对象</returns>
        public static ILogger GetLogger(this IServiceProvider provider, Type type)
        {
            Check.NotNull(type, nameof(type));
            ILoggerFactory factory = provider.GetRequiredService<ILoggerFactory>();
            return factory.CreateLogger(type);
        }

        /// <summary>
        /// 获取指定对象类型的日志对象
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="instance">要获取日志的类型对象，一般指当前类，即this</param>
        public static ILogger GetLogger(this IServiceProvider provider, object instance)
        {
            Check.NotNull(instance, nameof(instance));
            ILoggerFactory factory = provider.GetRequiredService<ILoggerFactory>();
            return factory.CreateLogger(instance.GetType());
        }

        /// <summary>
        /// 获取指定名称的日志对象
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public static ILogger GetLogger(this IServiceProvider provider, string name)
        {
            ILoggerFactory factory = provider.GetService<ILoggerFactory>();
            return factory.CreateLogger(name);
        }

        #endregion

        #region ScopedWork
        /// <summary>
        /// 执行 <see cref="ServiceLifetime.Scoped"/> 生命周期的业务逻辑
        /// </summary>
        /// <param name="rootProvider"></param>
        /// <param name="action"></param>
        public static void ExecuteScopedWork(this IServiceProvider rootProvider, Action<IServiceProvider> action)
        {
            using IServiceScope scope = rootProvider.CreateScope();
            action(scope.ServiceProvider);
        }

        /// <summary>
        /// 异步执行 <see cref="ServiceLifetime.Scoped"/> 生命周期的业务逻辑
        /// </summary>
        /// <param name="rootProvider"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public static async Task ExecuteScopedWorkAsync(this IServiceProvider rootProvider, Func<IServiceProvider, Task> action)
        {
            using IServiceScope scope = rootProvider.CreateScope();
            await action(scope.ServiceProvider);
        }

        /// <summary>
        /// 执行 <see cref="ServiceLifetime.Scoped"/> 生命周期的业务逻辑，并获取返回值
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="rootProvider"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static TResult ExecuteScopedWork<TResult>(this IServiceProvider rootProvider, Func<IServiceProvider, TResult> func)
        {
            using IServiceScope scope = rootProvider.CreateScope();
            return func(scope.ServiceProvider);
        }

        /// <summary>
        /// 异步执行 <see cref="ServiceLifetime.Scoped"/> 生命周期的业务逻辑，并获取返回值
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="rootProvider"></param>
        /// <param name="func"></param>
        /// <returns></returns>
        public static async Task<TResult> ExecuteScopedWorkAsync<TResult>(this IServiceProvider rootProvider, Func<IServiceProvider, Task<TResult>> func)
        {
            using IServiceScope scope = rootProvider.CreateScope();
            return await func(scope.ServiceProvider);
        }

        #endregion

    }
}